package com.DeviceTest;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.EthernetManager;
import android.net.IpConfiguration;
import android.net.IpConfiguration.IpAssignment;
import android.net.IpConfiguration.ProxySettings;
import android.net.StaticIpConfiguration;
import android.net.NetworkInfo;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.DeviceTest.helper.ConfigUtil;
import com.DeviceTest.helper.ControlButtonUtil;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;

import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;

public class EthernetTestActivity extends Activity {
    private static final String TAG = EthernetTestActivity.class.getSimpleName();

    public enum ETHERNET_STATE {
        ETHER_STATE_DISCONNECTED,
        ETHER_STATE_CONNECTING,
        ETHER_STATE_CONNECTED
    }

    private static final String HTTP_TEST_URL = "https://www.baidu.com/";
    private static final String nullIpInfo = "0.0.0.0";
    private static final String gettingIpInfo = "gettings...";
    private static final int TEST_GET_INFO_TIMEOUT_DELAY = 5000;
    private static final int TEST_FINISH_DELAY = 1500;

    private static final int MSG_GET_ETHERNET_STATE = 1;
    private static final int MSG_GET_ETHERNET_TIMEOUT = 2;
    private static final int MSG_HTTP_TEST = 3;
    private static final int MSG_TEST_FAILED = 4;
    private static final int MSG_TEST_SUCCESS = 5;

    private TextView txt_ethInfo;
    private TextView txt_result;
    private ProgressBar progressBar;
    private boolean mReadyToGetEthInfo;
    private boolean mStop;

    private EthernetManager mEthManager;
    private BroadcastReceiver mReceiver;
    private String mIfaceName;
    private String mEthIpAddress = null;
    private String mEthNetmask = null;
    private String mEthGateway = null;
    private String mEthdns1 = null;
    private String mEthdns2 = null;

    protected String mAssignIfaceName;

    protected void preData() {
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (mStop) {
                return;
            }
            switch (msg.what) {
                case MSG_GET_ETHERNET_STATE:
                    Log.v(TAG, "MSG_GET_ETHERNET_STATE");
                    if (mReadyToGetEthInfo) {
                        handleEtherStateChange((ETHERNET_STATE) msg.obj);
                    }
                    break;
                case MSG_GET_ETHERNET_TIMEOUT:
                    if (mReadyToGetEthInfo) {
                        mReadyToGetEthInfo = false;
                        Log.e(TAG, "MSG_GET_ETHERNET_TIMEOUT");
                        mHandler.removeMessages(MSG_GET_ETHERNET_TIMEOUT);
                        progressBar.setVisibility(View.GONE);
                        txt_result.setText(R.string.EthernetGetInfoTimeoutFail);
                        mHandler.sendEmptyMessageDelayed(MSG_TEST_FAILED, TEST_FINISH_DELAY);
                    }
                    break;
                case MSG_HTTP_TEST:
                    Log.v(TAG, "MSG_HTTP_TEST");
                    txt_result.setText("waiting test connect:\n" + HTTP_TEST_URL);
                    progressBar.setVisibility(View.VISIBLE);
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            mHandler.sendEmptyMessageDelayed(httpUrlTest() ? MSG_TEST_SUCCESS
                                    : MSG_TEST_FAILED, TEST_FINISH_DELAY);
                        }
                    }).start();
                    break;
                case MSG_TEST_SUCCESS:
                    Log.v(TAG, "MSG_TEST_SUCCESS");
                    mHandler.removeMessages(MSG_TEST_SUCCESS);
                    mStop = true;
                    findViewById(R.id.btn_Pass).performClick();
                    break;
                case MSG_TEST_FAILED:
                    Log.v(TAG, "MSG_TEST_FAILED");
                    mHandler.removeMessages(MSG_TEST_FAILED);
                    mStop = true;
                    findViewById(R.id.btn_Fail).performClick();
                    break;
                default:
                    break;
            }
        }
    };

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().addFlags(FLAG_FULLSCREEN | FLAG_KEEP_SCREEN_ON);
        setContentView(R.layout.ethernettest);

        preData();
        txt_ethInfo = (TextView) findViewById(R.id.txt_ethInfo);
        txt_result = (TextView) findViewById(R.id.txt_result);
        progressBar = (ProgressBar) findViewById(R.id.progress);
        ControlButtonUtil.initControlButtonView(this);
        findViewById(R.id.btn_Pass).setVisibility(View.INVISIBLE);
        findViewById(R.id.btn_Fail).setVisibility(View.INVISIBLE);

        mEthManager = (EthernetManager) getSystemService(Context.ETHERNET_SERVICE);
        if (null == mEthManager) {
            Log.e(TAG, "get ethernet manager failed");
            txt_result.setText(R.string.EthernetManagerFail);
            mHandler.sendEmptyMessageDelayed(MSG_TEST_FAILED, TEST_FINISH_DELAY);
            return;
        }
        String[] ifaces = new String[]{"eth0"};
        if (Build.VERSION.SDK_INT >= ConfigUtil.ANDROID_SDK_VERSION_P) {
            try {
                Method m = EthernetManager.class.getMethod("getAvailableInterfaces", null);
                ifaces = (String[]) m.invoke(mEthManager, null);
            } catch (Exception e) {
                e.printStackTrace();
                ifaces = null;
            }
        }
        if (ifaces.length > 0) {
            if (ConfigUtil.isSpecialEvb() && TextUtils.isEmpty(mAssignIfaceName)) {
                mAssignIfaceName = "eth0";
            }
            if (TextUtils.isEmpty(mAssignIfaceName)) {
                mIfaceName = ifaces[0];//"eth0";
            } else {
                for (String iface : ifaces) {
                    if (null != iface && iface.equals(mAssignIfaceName)) {
                        mIfaceName = iface;
                        break;
                    }
                }
            }
        }
        Log.v(TAG, "mIfaceName=" + mIfaceName);
        if (null == mIfaceName) {
            Log.e(TAG, "get ethernet ifaceName failed");
            txt_result.setText(R.string.EthernetInterfacesFail);
            mHandler.sendEmptyMessageDelayed(MSG_TEST_FAILED, TEST_FINISH_DELAY);
            return;
        }
        mReadyToGetEthInfo = true;
        progressBar.setVisibility(View.VISIBLE);
        mReceiver = new MyBroadcastReceiver();
        mHandler.sendEmptyMessageDelayed(MSG_GET_ETHERNET_TIMEOUT, TEST_GET_INFO_TIMEOUT_DELAY);
    }

    protected void onResume() {
        super.onResume();

        if (null != mReceiver) {
            IntentFilter localIntentFilter = new IntentFilter();
            localIntentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
            registerReceiver(mReceiver, localIntentFilter);
        }
    }

    public void onPause() {
        super.onPause();

        if (null != mReceiver) {
            unregisterReceiver(mReceiver);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mReadyToGetEthInfo = false;
        mStop = false;
        mHandler.removeMessages(MSG_GET_ETHERNET_STATE);
        mHandler.removeMessages(MSG_GET_ETHERNET_TIMEOUT);
        mHandler.removeMessages(MSG_TEST_FAILED);
        mHandler.removeMessages(MSG_TEST_SUCCESS);
    }

    private void getEthInfo() throws Exception {
        /*
        mEthHwAddress = mEthManager.getEthernetHwaddr(mEthManager.getEthernetIfaceName());
        if (mEthHwAddress == null) mEthHwAddress = nullIpInfo;
        */
        IpConfiguration ipConfiguration = null;
        if (Build.VERSION.SDK_INT >= ConfigUtil.ANDROID_SDK_VERSION_P) {
            Method m = EthernetManager.class.getMethod("getConfiguration", String.class);
            ipConfiguration = (IpConfiguration) m.invoke(mEthManager, mIfaceName);
        } else {
            Method m = EthernetManager.class.getMethod("getConfiguration", null);
            ipConfiguration = (IpConfiguration) m.invoke(mEthManager, null);
        }
        IpAssignment mode = ipConfiguration.getIpAssignment();
        if (mode == IpAssignment.DHCP || mode == IpAssignment.UNASSIGNED) {
            getEthInfoFromDhcp();
        } else if (mode == IpAssignment.STATIC) {
            getEthInfoFromStaticIp();
        }
    }

    public void getEthInfoFromDhcp() throws Exception {
        boolean isSdkAfterO = Build.VERSION.SDK_INT >= ConfigUtil.ANDROID_SDK_VERSION_P;
        String tempIpInfo;
        if (isSdkAfterO) {
            Method m = EthernetManager.class.getMethod("getIpAddress", String.class);
            tempIpInfo = (String) m.invoke(mEthManager, mIfaceName);
        } else {
            Method m = EthernetManager.class.getMethod("getIpAddress", null);
            tempIpInfo = (String) m.invoke(mEthManager, null);
        }

        if ((tempIpInfo != null) && (!tempIpInfo.equals(""))) {
            mEthIpAddress = tempIpInfo;
        } else {
            mEthIpAddress = nullIpInfo;
        }

        if (isSdkAfterO) {
            Method m = EthernetManager.class.getMethod("getNetmask", String.class);
            tempIpInfo = (String) m.invoke(mEthManager, mIfaceName);
        } else {
            Method m = EthernetManager.class.getMethod("getNetmask", null);
            tempIpInfo = (String) m.invoke(mEthManager, null);
        }

        if ((tempIpInfo != null) && (!tempIpInfo.equals(""))) {
            mEthNetmask = tempIpInfo;
        } else {
            mEthNetmask = nullIpInfo;
        }

        if (isSdkAfterO) {
            Method m = EthernetManager.class.getMethod("getGateway", String.class);
            tempIpInfo = (String) m.invoke(mEthManager, mIfaceName);
        } else {
            Method m = EthernetManager.class.getMethod("getGateway", null);
            tempIpInfo = (String) m.invoke(mEthManager, null);
        }
        if ((tempIpInfo != null) && (!tempIpInfo.equals(""))) {
            mEthGateway = tempIpInfo;
        } else {
            mEthGateway = nullIpInfo;
        }

        if (isSdkAfterO) {
            Method m = EthernetManager.class.getMethod("getDns", String.class);
            tempIpInfo = (String) m.invoke(mEthManager, mIfaceName);
        } else {
            Method m = EthernetManager.class.getMethod("getDns", null);
            tempIpInfo = (String) m.invoke(mEthManager, null);
        }
        if ((tempIpInfo != null) && (!tempIpInfo.equals(""))) {
            String data[] = tempIpInfo.split(",");
            mEthdns1 = data[0];
            if (data.length <= 1) {
                mEthdns2 = nullIpInfo;
            } else {
                mEthdns2 = data[1];
            }
        } else {
            mEthdns1 = nullIpInfo;
        }
    }

    public void getEthInfoFromStaticIp() throws Exception {
        IpConfiguration ipConfiguration = null;
        if (Build.VERSION.SDK_INT >= ConfigUtil.ANDROID_SDK_VERSION_P) {
            Method m = EthernetManager.class.getMethod("getConfiguration", String.class);
            ipConfiguration = (IpConfiguration) m.invoke(mEthManager, mIfaceName);
        } else {
            Method m = EthernetManager.class.getMethod("getConfiguration", null);
            ipConfiguration = (IpConfiguration) m.invoke(mEthManager, null);
        }
        StaticIpConfiguration staticIpConfiguration = ipConfiguration.getStaticIpConfiguration();

        if (staticIpConfiguration == null) {
            return;
        }
        LinkAddress ipAddress = staticIpConfiguration.ipAddress;
        InetAddress gateway = staticIpConfiguration.gateway;
        ArrayList<InetAddress> dnsServers = staticIpConfiguration.dnsServers;

        if (ipAddress != null) {
            mEthIpAddress = ipAddress.getAddress().getHostAddress();
            mEthNetmask = interMask2String(ipAddress.getPrefixLength());
        }
        if (gateway != null) {
            mEthGateway = gateway.getHostAddress();
        }
        mEthdns1 = dnsServers.get(0).getHostAddress();

        if (dnsServers.size() > 1) { /* 只保留两个*/
            mEthdns2 = dnsServers.get(1).getHostAddress();
        }
    }

    private void handleEtherStateChange(ETHERNET_STATE EtherState, long delayMillis) {
        mHandler.removeMessages(MSG_GET_ETHERNET_STATE);
        if (delayMillis > 0) {
            Message msg = new Message();
            msg.what = MSG_GET_ETHERNET_STATE;
            msg.obj = EtherState;
            mHandler.sendMessageDelayed(msg, delayMillis);
        } else {
            handleEtherStateChange(EtherState);
        }
    }

    private void handleEtherStateChange(ETHERNET_STATE EtherState) {
        Log.v(TAG, "curEtherState" + EtherState);
        progressBar.setVisibility(View.VISIBLE);
        switch (EtherState) {
            case ETHER_STATE_DISCONNECTED:
                /*mEthIpAddress = nullIpInfo;
                mEthNetmask = nullIpInfo;
                mEthGateway = nullIpInfo;
                mEthdns1 = nullIpInfo;
                mEthdns2 = nullIpInfo;
                refreshUI();
                break;*/
            case ETHER_STATE_CONNECTING:
                mEthIpAddress = gettingIpInfo;
                mEthNetmask = gettingIpInfo;
                mEthGateway = gettingIpInfo;
                mEthdns1 = gettingIpInfo;
                mEthdns2 = gettingIpInfo;
                txt_ethInfo.setText(gettingIpInfo);
                break;
            case ETHER_STATE_CONNECTED:
                try {
                    getEthInfo();
                    refreshUI();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;
            default:
                break;
        }
    }

    private void refreshUI() {
        StringBuilder sb = new StringBuilder();
        sb.append(mIfaceName + "\n");
        sb.append("ip: " + mEthIpAddress + "\n");
        sb.append("netmask: " + mEthNetmask + "\n");
        sb.append("gateway: " + mEthGateway + "\n");
        sb.append("dns1: " + mEthdns1 + "\n");
        sb.append("dns2: " + mEthdns2 + "\n");
        Log.v(TAG, sb.toString());
        txt_ethInfo.setText(sb.toString());
        progressBar.setVisibility(View.GONE);
        if (null == mEthIpAddress || mEthIpAddress.equals(nullIpInfo) || mEthIpAddress.equals(gettingIpInfo)
                || null == mEthNetmask || mEthNetmask.equals(nullIpInfo) || mEthNetmask.equals(gettingIpInfo)
                || null == mEthGateway || mEthGateway.equals(nullIpInfo) || mEthGateway.equals(gettingIpInfo)
                || null == mEthdns1 || mEthdns1.equals(nullIpInfo) || mEthdns1.equals(gettingIpInfo)
            /*|| null == mEthdns2 || mEthdns2.equals(nullIpInfo) || mEthdns2.equals(gettingIpInfo)*/) {

        } else if (mReadyToGetEthInfo) {
            mReadyToGetEthInfo = false;
            mHandler.removeMessages(MSG_GET_ETHERNET_TIMEOUT);
            mHandler.sendEmptyMessage(MSG_HTTP_TEST);
        }
    }

    //将子网掩码转换成ip子网掩码形式，比如输入32输出为255.255.255.255
    public String interMask2String(int prefixLength) {
        String netMask = null;
        int inetMask = prefixLength;

        int part = inetMask / 8;
        int remainder = inetMask % 8;
        int sum = 0;

        for (int i = 8; i > 8 - remainder; i--) {
            sum = sum + (int) Math.pow(2, i - 1);
        }

        if (part == 0) {
            netMask = sum + ".0.0.0";
        } else if (part == 1) {
            netMask = "255." + sum + ".0.0";
        } else if (part == 2) {
            netMask = "255.255." + sum + ".0";
        } else if (part == 3) {
            netMask = "255.255.255." + sum;
        } else if (part == 4) {
            netMask = "255.255.255.255";
        }

        return netMask;
    }

    private boolean httpUrlTest() {
        HttpURLConnection conn = null;
        InputStream is = null;
        String resultData = "";
        try {
            URL url = new URL(HTTP_TEST_URL);
            conn = (HttpURLConnection) url.openConnection();
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.setUseCaches(false);
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(10000);
            conn.setReadTimeout(1000);
            if (HttpURLConnection.HTTP_OK == conn.getResponseCode()) {
                is = conn.getInputStream();
                InputStreamReader isr = new InputStreamReader(is);
                BufferedReader bufferReader = new BufferedReader(isr);
                String inputLine = "";
                while ((inputLine = bufferReader.readLine()) != null) {
                    resultData += inputLine + "\n";
                }
                Log.v(TAG, "http respond:" + resultData);
                return resultData.length() > 20;
            } else {
                Log.e(TAG, "==========error code:" + conn.getResponseCode());
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                conn.disconnect();
            }
        }
        return false;
    }

    public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
            return false;
        }
        return super.dispatchKeyEvent(event);
    }

    class MyBroadcastReceiver extends BroadcastReceiver {

        public void onReceive(Context context, Intent intent) {
            if (!mReadyToGetEthInfo || mStop) {
                return;
            }
            String action = intent.getAction();
            Log.v(TAG, "action:" + action);
            if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
                NetworkInfo info = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
                Log.v(TAG, "===" + info.toString());
                if (null != info && ConnectivityManager.TYPE_ETHERNET == info.getType()) {
                    if (NetworkInfo.State.CONNECTED == info.getState()) {
                        handleEtherStateChange(ETHERNET_STATE.ETHER_STATE_CONNECTED, 0);
                    } else if (NetworkInfo.State.DISCONNECTED == info.getState()) {
                        handleEtherStateChange(ETHERNET_STATE.ETHER_STATE_DISCONNECTED, 0);
                    }
                }
            }
        }
    }
}